package com.intlke.example.app.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author fengwenping
 * @version 1.0.0 (2023/8/27 00:24)
 * <p>描述:</p>
 * <p>MyBatis手动验证SQL工具类,可以快速的验证</p>
 */
public class MyBatisUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyBatisUtils.class);
    private static volatile SqlSessionFactory SQL_SESSION_FACTORY = null;
    private static volatile MyBatisUtils instance = null;

    static {
        try {
            SQL_SESSION_FACTORY = getSqlSessionFactory();
        } catch (Exception var1) {
            LOGGER.error("init sqlSessionFactory failure", var1);
        }
    }

    private MyBatisUtils() {
    }

    public static MyBatisUtils getInstance() {
        if (Objects.isNull(instance)) {
            synchronized (MyBatisUtils.class) {
                if (Objects.isNull(instance)) {
                    instance = new MyBatisUtils();
                }
            }
        }
        return instance;
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        if (Objects.isNull(SQL_SESSION_FACTORY)) {
            String resource = "mybatis-config-test.xml";
            try {
                try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
                    SQL_SESSION_FACTORY = (new SqlSessionFactoryBuilder()).build(inputStream);
                }
            } catch (IOException var14) {
                LOGGER.error("get sqlSessionFactory failure", var14);
                if (var14 instanceof FileNotFoundException && Objects.isNull(SQL_SESSION_FACTORY)) {
                    resource = "mybatis-config.xml";
                    try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
                        SQL_SESSION_FACTORY = (new SqlSessionFactoryBuilder()).build(inputStream);
                    } catch (IOException var15) {
                        LOGGER.error("get sqlSessionFactory failure", var15);
                    }
                }
            }
        }
        return SQL_SESSION_FACTORY;
    }

    public static SqlSession openSession(SqlSessionFactory sqlSessionFactory) {
        return sqlSessionFactory.openSession();
    }

    public <T, R> R call(Class<T> mapperInterface, Function<T, R> mapperExecutor) {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = openSession(sqlSessionFactory);
        R result = null;
        try {
            T mapper = sqlSession.getMapper(mapperInterface);
            result = mapperExecutor.apply(mapper);
            sqlSession.commit();
        } catch (Exception var10) {
            sqlSession.rollback();
            LOGGER.error("mybatis execute sql failure", var10);
        } finally {
            if (Objects.nonNull(sqlSession)) {
                sqlSession.close();
            }
        }
        return result;
    }

    public <T> void run(Class<T> mapperInterface, Consumer<T> mapperExecutor) {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = openSession(sqlSessionFactory);
        try {
            T mapper = sqlSession.getMapper(mapperInterface);
            mapperExecutor.accept(mapper);
            sqlSession.commit();
        } catch (Exception var9) {
            sqlSession.rollback();
            LOGGER.error("mybatis execute sql failure", var9);
        } finally {
            if (Objects.nonNull(sqlSession)) {
                sqlSession.close();
            }
        }

    }


}
